From 48781cf7f7b67fe2f769423150b8fecce67a3549 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 22 Sep 2021 02:01:41 +0200 Subject: [PATCH] memorytexture: Split out GdkMemoryFormat handling Also, now make gdk_memory_convert() the only conversion functions and allow conversions between any 2 formats by going via a float[4]. This could be optimized via fast-paths, but so far it isn't. --- gdk/gdkglcontext.c | 3 +- gdk/gdkgltexture.c | 1 + gdk/gdkmemoryformat.c | 366 ++++++++++++++++++++++++ gdk/gdkmemoryformatprivate.h | 42 +++ gdk/gdkmemorytexture.c | 518 +--------------------------------- gdk/gdkmemorytextureprivate.h | 35 --- gdk/loaders/gdkpng.c | 1 + gdk/loaders/gdktiff.c | 1 + gdk/meson.build | 1 + gsk/ngl/gsknglcommandqueue.c | 1 + gsk/ngl/gsknglglyphlibrary.c | 4 +- gsk/ngl/gskngliconlibrary.c | 4 +- 12 files changed, 430 insertions(+), 547 deletions(-) create mode 100644 gdk/gdkmemoryformat.c create mode 100644 gdk/gdkmemoryformatprivate.h diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 11c3f77dd4..ece50c8cd2 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -79,6 +79,7 @@ #include "gdkdebug.h" #include "gdkdisplayprivate.h" #include "gdkintl.h" +#include "gdkmemoryformatprivate.h" #include "gdkmemorytextureprivate.h" #include "gdkprofilerprivate.h" @@ -303,7 +304,7 @@ gdk_gl_context_upload_texture (GdkGLContext *context, { copy = g_malloc (width * height * 4); gdk_memory_convert (copy, width * 4, - GDK_MEMORY_CONVERT_GLES_RGBA, + GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, data, stride, data_format, width, height); data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c index e2e292964d..1a321fa879 100644 --- a/gdk/gdkgltexture.c +++ b/gdk/gdkgltexture.c @@ -21,6 +21,7 @@ #include "gdkgltextureprivate.h" #include "gdkdisplayprivate.h" +#include "gdkmemoryformatprivate.h" #include "gdkmemorytextureprivate.h" #include "gdktextureprivate.h" diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c new file mode 100644 index 0000000000..2a4cfa1e92 --- /dev/null +++ b/gdk/gdkmemoryformat.c @@ -0,0 +1,366 @@ +/* + * Copyright © 2021 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gdkmemoryformatprivate.h" + +#include "gsk/ngl/fp16private.h" + +typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription; + +typedef enum { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + GDK_MEMORY_ALPHA_STRAIGHT, + GDK_MEMORY_ALPHA_OPAQUE +} GdkMemoryAlpha; + +#define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \ +static void \ +name ## _to_float (float *dest, \ + const guchar *src_data, \ + gsize n) \ +{ \ + for (gsize i = 0; i < n; i++) \ + { \ + T *src = (T *) (src_data + i * bpp); \ + dest[0] = (float) src[R] / scale; \ + dest[1] = (float) src[G] / scale; \ + dest[2] = (float) src[B] / scale; \ + if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \ + dest += 4; \ + } \ +} \ +\ +static void \ +name ## _from_float (guchar *dest_data, \ + const float *src, \ + gsize n) \ +{ \ + for (gsize i = 0; i < n; i++) \ + { \ + T *dest = (T *) (dest_data + i * bpp); \ + dest[R] = CLAMP (src[0] * scale + 0.5, 0, scale); \ + dest[G] = CLAMP (src[1] * scale + 0.5, 0, scale); \ + dest[B] = CLAMP (src[2] * scale + 0.5, 0, scale); \ + if (A >= 0) dest[A] = CLAMP (src[3] * scale + 0.5, 0, scale); \ + src += 4; \ + } \ +} + +TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255) +TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255) +TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255) +TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255) +TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255) +TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255) +TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255) +TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255) +TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255) +TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535) +TYPED_FUNCS (r16g16b16a16, guint16, 0, 1, 2, 3, 8, 65535) + +static void +r16g16b16_float_to_float (float *dest, + const guchar *src_data, + gsize n) +{ + guint16 *src = (guint16 *) src_data; + for (gsize i = 0; i < n; i++) + { + half_to_float (src, dest, 3); + dest[3] = 1.0; + dest += 4; + src += 3; + } +} + +static void +r16g16b16_float_from_float (guchar *dest_data, + const float *src, + gsize n) +{ + guint16 *dest = (guint16 *) dest_data; + for (gsize i = 0; i < n; i++) + { + float_to_half (src, dest, 3); + dest += 3; + src += 4; + } +} + +static void +r16g16b16a16_float_to_float (float *dest, + const guchar *src, + gsize n) +{ + half_to_float ((const guint16 *) src, dest, 4 * n); +} + +static void +r16g16b16a16_float_from_float (guchar *dest, + const float *src, + gsize n) +{ + float_to_half (src, (guint16 *) dest, 4 * n); +} + +static void +r32g32b32_float_to_float (float *dest, + const guchar *src_data, + gsize n) +{ + float *src = (float *) src_data; + for (gsize i = 0; i < n; i++) + { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = 1.0; + dest += 4; + src += 3; + } +} + +static void +r32g32b32_float_from_float (guchar *dest_data, + const float *src, + gsize n) +{ + float *dest = (float *) dest_data; + for (gsize i = 0; i < n; i++) + { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest += 3; + src += 4; + } +} + +static void +r32g32b32a32_float_to_float (float *dest, + const guchar *src, + gsize n) +{ + memcpy (dest, src, sizeof (float) * n * 4); +} + +static void +r32g32b32a32_float_from_float (guchar *dest, + const float *src, + gsize n) +{ + memcpy (dest, src, sizeof (float) * n * 4); +} + +struct _GdkMemoryFormatDescription +{ + GdkMemoryAlpha alpha; + gsize bytes_per_pixel; + gsize alignment; + + /* no premultiplication going on here */ + void (* to_float) (float *, const guchar*, gsize); + void (* from_float) (guchar *, const float *, gsize); +}; + +static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { + [GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 4, + G_ALIGNOF (guchar), + b8g8r8a8_premultiplied_to_float, + b8g8r8a8_premultiplied_from_float, + }, + [GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 4, + G_ALIGNOF (guchar), + a8r8g8b8_premultiplied_to_float, + a8r8g8b8_premultiplied_from_float, + }, + [GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 4, + G_ALIGNOF (guchar), + r8g8b8a8_premultiplied_to_float, + r8g8b8a8_premultiplied_from_float, + }, + [GDK_MEMORY_B8G8R8A8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 4, + G_ALIGNOF (guchar), + b8g8r8a8_to_float, + b8g8r8a8_from_float, + }, + [GDK_MEMORY_A8R8G8B8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 4, + G_ALIGNOF (guchar), + a8r8g8b8_to_float, + a8r8g8b8_from_float, + }, + [GDK_MEMORY_R8G8B8A8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 4, + G_ALIGNOF (guchar), + r8g8b8a8_to_float, + r8g8b8a8_from_float, + }, + [GDK_MEMORY_A8B8G8R8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 4, + G_ALIGNOF (guchar), + a8b8g8r8_to_float, + a8b8g8r8_from_float, + }, + [GDK_MEMORY_R8G8B8] = { + GDK_MEMORY_ALPHA_OPAQUE, + 3, + G_ALIGNOF (guchar), + r8g8b8_to_float, + r8g8b8_from_float, + }, + [GDK_MEMORY_B8G8R8] = { + GDK_MEMORY_ALPHA_OPAQUE, + 3, + G_ALIGNOF (guchar), + b8g8r8_to_float, + b8g8r8_from_float, + }, + [GDK_MEMORY_R16G16B16] = { + GDK_MEMORY_ALPHA_OPAQUE, + 6, + G_ALIGNOF (guint16), + r16g16b16_to_float, + r16g16b16_from_float, + }, + [GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 8, + G_ALIGNOF (guint16), + r16g16b16a16_to_float, + r16g16b16a16_from_float, + }, + [GDK_MEMORY_R16G16B16_FLOAT] = { + GDK_MEMORY_ALPHA_OPAQUE, + 6, + G_ALIGNOF (guint16), + r16g16b16_float_to_float, + r16g16b16_float_from_float, + }, + [GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 8, + G_ALIGNOF (guint16), + r16g16b16a16_float_to_float, + r16g16b16a16_float_from_float, + }, + [GDK_MEMORY_R32G32B32_FLOAT] = { + GDK_MEMORY_ALPHA_OPAQUE, + 12, + G_ALIGNOF (float), + r32g32b32_float_to_float, + r32g32b32_float_from_float, + }, + [GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 16, + G_ALIGNOF (float), + r32g32b32a32_float_to_float, + r32g32b32a32_float_from_float, + } +}; + +gsize +gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) +{ + return memory_formats[format].bytes_per_pixel; +} + +gsize +gdk_memory_format_alignment (GdkMemoryFormat format) +{ + return memory_formats[format].alignment; +} + +static void +premultiply (float *rgba, + gsize n) +{ + for (gsize i = 0; i < n; i++) + { + rgba[0] *= rgba[3]; + rgba[1] *= rgba[3]; + rgba[2] *= rgba[3]; + rgba += 4; + } +} + +static void +unpremultiply (float *rgba, + gsize n) +{ + for (gsize i = 0; i < n; i++) + { + if (rgba[3] > 1/255.0) + { + rgba[0] /= rgba[3]; + rgba[1] /= rgba[3]; + rgba[2] /= rgba[3]; + } + rgba += 4; + } +} + +void +gdk_memory_convert (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height) +{ + const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format]; + const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format]; + float *tmp; + gsize y; + + g_assert (dest_format < GDK_MEMORY_N_FORMATS); + g_assert (src_format < GDK_MEMORY_N_FORMATS); + + tmp = g_new (float, width * 4); + + for (y = 0; y < height; y++) + { + src_desc->to_float (tmp, src_data, width); + if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT) + unpremultiply (tmp, width); + else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT) + premultiply (tmp, width); + dest_desc->from_float (dest_data, tmp, width); + src_data += src_stride; + dest_data += dest_stride; + } + + g_free (tmp); +} diff --git a/gdk/gdkmemoryformatprivate.h b/gdk/gdkmemoryformatprivate.h new file mode 100644 index 0000000000..0de89f0756 --- /dev/null +++ b/gdk/gdkmemoryformatprivate.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2021 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GDK_MEMORY_CONVERT_PRIVATE_H__ +#define __GDK_MEMORY_CONVERT_PRIVATE_H__ + +#include "gdkmemorytexture.h" + +G_BEGIN_DECLS + +gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST; +gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST; + +void gdk_memory_convert (guchar *dest_data, + gsize dest_stride, + GdkMemoryFormat dest_format, + const guchar *src_data, + gsize src_stride, + GdkMemoryFormat src_format, + gsize width, + gsize height); + + +G_END_DECLS + +#endif /* __GDK_MEMORY_CONVERT_PRIVATE_H__ */ diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c index 6c08ef531b..33ba90fe5c 100644 --- a/gdk/gdkmemorytexture.c +++ b/gdk/gdkmemorytexture.c @@ -20,6 +20,8 @@ #include "config.h" #include "gdkmemorytextureprivate.h" + +#include "gdkmemoryformatprivate.h" #include "gsk/ngl/fp16private.h" /** @@ -45,80 +47,6 @@ struct _GdkMemoryTextureClass G_DEFINE_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK_TYPE_TEXTURE) -gsize -gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) -{ - switch (format) - { - case GDK_MEMORY_R8G8B8: - case GDK_MEMORY_B8G8R8: - return 3; - - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - return 4; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16_FLOAT: - return 6; - - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - return 8; - - case GDK_MEMORY_R32G32B32_FLOAT: - return 12; - - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - return 16; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return 4; - } -} - -static gsize -gdk_memory_format_alignment (GdkMemoryFormat format) -{ - switch (format) - { - case GDK_MEMORY_R8G8B8: - case GDK_MEMORY_B8G8R8: - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - return G_ALIGNOF (guchar); - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16_FLOAT: - return G_ALIGNOF (guint16); - - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - return G_ALIGNOF (guint16); - - case GDK_MEMORY_R32G32B32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - return G_ALIGNOF (float); - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return G_ALIGNOF (double); - } -} - static void gdk_memory_texture_dispose (GObject *object) { @@ -143,7 +71,7 @@ gdk_memory_texture_download (GdkTexture *texture, GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture); gdk_memory_convert (data, stride, - GDK_MEMORY_CONVERT_DOWNLOAD, + GDK_MEMORY_DEFAULT, (guchar *) g_bytes_get_data (self->bytes, NULL), self->stride, self->format, @@ -158,12 +86,14 @@ gdk_memory_texture_download_float (GdkTexture *texture, { GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture); - gdk_memory_convert_to_float (data, stride, - (guchar *) g_bytes_get_data (self->bytes, NULL), - self->stride, - self->format, - gdk_texture_get_width (texture), - gdk_texture_get_height (texture)); + gdk_memory_convert ((guchar *) data, + stride * sizeof (float), + GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, + (guchar *) g_bytes_get_data (self->bytes, NULL), + self->stride, + self->format, + gdk_texture_get_width (texture), + gdk_texture_get_height (texture)); } static void @@ -279,429 +209,3 @@ gdk_memory_texture_get_stride (GdkMemoryTexture *self) return self->stride; } -static void -convert_memcpy (guchar *dest_data, - gsize dest_stride, - const guchar *src_data, - gsize src_stride, - gsize width, - gsize height) -{ - gsize y; - - for (y = 0; y < height; y++) - memcpy (dest_data + y * dest_stride, src_data + y * src_stride, 4 * width); -} - -#define SWIZZLE(A,R,G,B) \ -static void \ -convert_swizzle ## A ## R ## G ## B (guchar *dest_data, \ - gsize dest_stride, \ - const guchar *src_data, \ - gsize src_stride, \ - gsize width, \ - gsize height) \ -{ \ - gsize x, y; \ -\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - dest_data[4 * x + A] = src_data[4 * x + 0]; \ - dest_data[4 * x + R] = src_data[4 * x + 1]; \ - dest_data[4 * x + G] = src_data[4 * x + 2]; \ - dest_data[4 * x + B] = src_data[4 * x + 3]; \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -} - -SWIZZLE(3,2,1,0) -SWIZZLE(2,1,0,3) -SWIZZLE(3,0,1,2) -SWIZZLE(1,2,3,0) - -#define SWIZZLE_OPAQUE(A,R,G,B) \ -static void \ -convert_swizzle_opaque_## A ## R ## G ## B (guchar *dest_data, \ - gsize dest_stride, \ - const guchar *src_data, \ - gsize src_stride, \ - gsize width, \ - gsize height) \ -{ \ - gsize x, y; \ -\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - dest_data[4 * x + A] = 0xFF; \ - dest_data[4 * x + R] = src_data[3 * x + 0]; \ - dest_data[4 * x + G] = src_data[3 * x + 1]; \ - dest_data[4 * x + B] = src_data[3 * x + 2]; \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -} - -SWIZZLE_OPAQUE(3,2,1,0) -SWIZZLE_OPAQUE(3,0,1,2) -SWIZZLE_OPAQUE(0,1,2,3) -SWIZZLE_OPAQUE(0,3,2,1) - -#define PREMULTIPLY(d,c,a) G_STMT_START { guint t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END -#define SWIZZLE_PREMULTIPLY(A,R,G,B, A2,R2,G2,B2) \ -static void \ -convert_swizzle_premultiply_ ## A ## R ## G ## B ## _ ## A2 ## R2 ## G2 ## B2 \ - (guchar *dest_data, \ - gsize dest_stride, \ - const guchar *src_data, \ - gsize src_stride, \ - gsize width, \ - gsize height) \ -{ \ - gsize x, y; \ -\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - dest_data[4 * x + A] = src_data[4 * x + A2]; \ - PREMULTIPLY(dest_data[4 * x + R], src_data[4 * x + R2], src_data[4 * x + A2]); \ - PREMULTIPLY(dest_data[4 * x + G], src_data[4 * x + G2], src_data[4 * x + A2]); \ - PREMULTIPLY(dest_data[4 * x + B], src_data[4 * x + B2], src_data[4 * x + A2]); \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -} - -SWIZZLE_PREMULTIPLY (3,2,1,0, 3,2,1,0) -SWIZZLE_PREMULTIPLY (0,1,2,3, 3,2,1,0) -SWIZZLE_PREMULTIPLY (3,2,1,0, 0,1,2,3) -SWIZZLE_PREMULTIPLY (0,1,2,3, 0,1,2,3) -SWIZZLE_PREMULTIPLY (3,2,1,0, 3,0,1,2) -SWIZZLE_PREMULTIPLY (0,1,2,3, 3,0,1,2) -SWIZZLE_PREMULTIPLY (3,2,1,0, 0,3,2,1) -SWIZZLE_PREMULTIPLY (0,1,2,3, 0,3,2,1) -SWIZZLE_PREMULTIPLY (3,0,1,2, 3,2,1,0) -SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3) -SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2) -SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1) - -#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \ -static void \ -convert_ ## name ## _to_ ## suffix (guchar *dest_data, \ - gsize dest_stride, \ - const guchar *src_data, \ - gsize src_stride, \ - gsize width, \ - gsize height) \ -{ \ - gsize x, y; \ -\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - guchar conv[4]; \ - convert_pixel_ ## name (conv, src_data + step * x); \ - dest_data[4 * x + R] = conv[0]; \ - dest_data[4 * x + G] = conv[1]; \ - dest_data[4 * x + B] = conv[2]; \ - dest_data[4 * x + A] = conv[3]; \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -} - -#define CONVERT_FUNCS(name,step) \ -CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \ -CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \ -CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \ - -static inline void -convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data) -{ - const guint16 *src = (const guint16 *) src_data; - dest_data[0] = (guchar)(src[0] >> 8); - dest_data[1] = (guchar)(src[1] >> 8); - dest_data[2] = (guchar)(src[2] >> 8); - dest_data[3] = 0xFF; -} -CONVERT_FUNCS(rgb16, 3 * sizeof (guint16)) - -static inline void -convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data) -{ - const guint16 *src = (const guint16 *) src_data; - dest_data[0] = (guchar)(src[0] >> 8); - dest_data[1] = (guchar)(src[1] >> 8); - dest_data[2] = (guchar)(src[2] >> 8); - dest_data[3] = (guchar)(src[3] >> 8); -} -CONVERT_FUNCS(rgba16, 4 * sizeof (guint16)) - -static inline void -convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data) -{ - float src[4]; - guint16 tmp[4]; - memcpy(tmp, src_data, sizeof(guint16) * 3); - half_to_float4(tmp, src); - dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f); - dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f); - dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f); - dest_data[3] = 0xFF; -} -CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16)) - -static inline void -convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data) -{ - float src[4]; - half_to_float4((const guint16 *) src_data, src); - dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f); - dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f); - dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f); - dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f); -} -CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16)) - -static inline void -convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data) -{ - float *src = (float *) src_data; - dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f); - dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f); - dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f); - dest_data[3] = 0xFF; -} -CONVERT_FUNCS(rgb32f, 3 * sizeof (float)) - -static inline void -convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data) -{ - float *src = (float *) src_data; - dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f); - dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f); - dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f); - dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f); -} -CONVERT_FUNCS(rgba32f, 4 * sizeof (float)) - -typedef void (* ConversionFunc) (guchar *dest_data, - gsize dest_stride, - const guchar *src_data, - gsize src_stride, - gsize width, - gsize height); - -static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] = -{ - { convert_memcpy, convert_swizzle3210, convert_swizzle2103 }, - { convert_swizzle3210, convert_memcpy, convert_swizzle3012 }, - { convert_swizzle2103, convert_swizzle1230, convert_memcpy }, - { convert_swizzle_premultiply_3210_3210, convert_swizzle_premultiply_0123_3210, convert_swizzle_premultiply_3012_3210, }, - { convert_swizzle_premultiply_3210_0123, convert_swizzle_premultiply_0123_0123, convert_swizzle_premultiply_3012_0123 }, - { convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 }, - { convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, convert_swizzle_premultiply_3012_0321 }, - { convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 }, - { convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 }, - { convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba }, - { convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba }, - { convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba }, - { convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba }, - { convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba }, - { convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba } -}; - -void -gdk_memory_convert (guchar *dest_data, - gsize dest_stride, - GdkMemoryConversion dest_format, - const guchar *src_data, - gsize src_stride, - GdkMemoryFormat src_format, - gsize width, - gsize height) -{ - g_assert (dest_format < 3); - g_assert (src_format < GDK_MEMORY_N_FORMATS); - - converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height); -} - -#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - if (A >= 0) \ - { \ - dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \ - dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \ - dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \ - dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \ - if (premultiply) \ - { \ - dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \ - dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \ - dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \ - } \ - } \ - else \ - { \ - dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \ - dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \ - dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \ - dest_data[4 * x + 3] = 1.0; \ - } \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -}G_STMT_END - -#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\ - for (y = 0; y < height; y++) \ - { \ - for (x = 0; x < width; x++) \ - { \ - func (dest_data + 4 * x, src_data + step * x); \ - } \ -\ - dest_data += dest_stride; \ - src_data += src_stride; \ - } \ -}G_STMT_END - -static inline void -convert_rgb16_to_float (float *dest, const guchar *src_data) -{ - const guint16 *src = (const guint16 *) src_data; - dest[0] = src[0] / 65535.f; - dest[1] = src[1] / 65535.f; - dest[2] = src[2] / 65535.f; - dest[3] = 1.0; -} - -static inline void -convert_rgba16_to_float (float *dest, const guchar *src_data) -{ - const guint16 *src = (const guint16 *) src_data; - dest[0] = src[0] / 65535.f; - dest[1] = src[1] / 65535.f; - dest[2] = src[2] / 65535.f; - dest[3] = src[3] / 65535.f; -} - -static inline void -convert_rgb16f_to_float (float *dest, const guchar *src_data) -{ - guint16 tmp[4]; - memcpy(tmp, src_data, sizeof(guint16) * 3); - tmp[3] = FP16_ONE; - half_to_float4 (tmp, dest); -} - -static inline void -convert_rgba16f_to_float (float *dest, const guchar *src_data) -{ - half_to_float4 ((const guint16 *) src_data, dest); -} - -static inline void -convert_rgb32f_to_float (float *dest, const guchar *src_data) -{ - const float *src = (const float *) src_data; - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - dest[3] = 1.0; -} - -static inline void -convert_rgba32f_to_float (float *dest, const guchar *src_data) -{ - const float *src = (const float *) src_data; - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - dest[3] = src[3]; -} - -void -gdk_memory_convert_to_float (float *dest_data, - gsize dest_stride, - const guchar *src_data, - gsize src_stride, - GdkMemoryFormat src_format, - gsize width, - gsize height) -{ - gsize x, y; - - switch (src_format) - { - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - CONVERT_FLOAT (2, 1, 0, 3, FALSE); - break; - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - CONVERT_FLOAT (1, 2, 3, 0, FALSE); - break; - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - CONVERT_FLOAT (0, 1, 2, 3, FALSE); - break; - case GDK_MEMORY_B8G8R8A8: - CONVERT_FLOAT (2, 1, 0, 3, TRUE); - break; - case GDK_MEMORY_A8R8G8B8: - CONVERT_FLOAT (1, 2, 3, 0, TRUE); - break; - case GDK_MEMORY_R8G8B8A8: - CONVERT_FLOAT (0, 1, 2, 3, TRUE); - break; - case GDK_MEMORY_A8B8G8R8: - CONVERT_FLOAT (3, 2, 1, 0, TRUE); - break; - case GDK_MEMORY_R8G8B8: - CONVERT_FLOAT (0, 1, 2, -1, FALSE); - break; - case GDK_MEMORY_B8G8R8: - CONVERT_FLOAT (2, 1, 0, -1, FALSE); - break; - case GDK_MEMORY_R16G16B16: - CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16)); - break; - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16)); - break; - case GDK_MEMORY_R16G16B16_FLOAT: - CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16)); - break; - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16)); - break; - case GDK_MEMORY_R32G32B32_FLOAT: - CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float)); - break; - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float)); - break; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached(); - } -} diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h index ddd9fd1c37..f61cccb9ef 100644 --- a/gdk/gdkmemorytextureprivate.h +++ b/gdk/gdkmemorytextureprivate.h @@ -29,45 +29,10 @@ G_BEGIN_DECLS #define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8 #define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8 -typedef enum { - GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN, - GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN, - GDK_MEMORY_CONVERT_GLES_RGBA, - - GDK_MEMORY_N_CONVERSIONS -} GdkMemoryConversion; - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN -#elif G_BYTE_ORDER == G_BIG_ENDIAN -#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN -#else -#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD" -#endif - -gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format); - GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *self); const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self); gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self); -void gdk_memory_convert (guchar *dest_data, - gsize dest_stride, - GdkMemoryConversion dest_format, - const guchar *src_data, - gsize src_stride, - GdkMemoryFormat src_format, - gsize width, - gsize height); - -void gdk_memory_convert_to_float (float *dest_data, - gsize dest_stride, - const guchar *src_data, - gsize src_stride, - GdkMemoryFormat src_format, - gsize width, - gsize height); - G_END_DECLS diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c index 97e6dfffd0..df453fc6a3 100644 --- a/gdk/loaders/gdkpng.c +++ b/gdk/loaders/gdkpng.c @@ -20,6 +20,7 @@ #include "gdkpngprivate.h" #include "gdkintl.h" +#include "gdkmemoryformatprivate.h" #include "gdkmemorytextureprivate.h" #include "gdkprofilerprivate.h" #include "gdktexture.h" diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c index d7416391ee..ed1b0e566b 100644 --- a/gdk/loaders/gdktiff.c +++ b/gdk/loaders/gdktiff.c @@ -20,6 +20,7 @@ #include "gdktiffprivate.h" #include "gdkintl.h" +#include "gdkmemoryformatprivate.h" #include "gdkmemorytextureprivate.h" #include "gdkprofilerprivate.h" #include "gdktexture.h" diff --git a/gdk/meson.build b/gdk/meson.build index 06905233f8..0756f7667c 100644 --- a/gdk/meson.build +++ b/gdk/meson.build @@ -30,6 +30,7 @@ gdk_public_sources = files([ 'gdkhsla.c', 'gdkkeys.c', 'gdkkeyuni.c', + 'gdkmemoryformat.c', 'gdkmemorytexture.c', 'gdkmonitor.c', 'gdkpaintable.c', diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c index a5fbf0dc8d..b2a474cf59 100644 --- a/gsk/ngl/gsknglcommandqueue.c +++ b/gsk/ngl/gsknglcommandqueue.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/gsk/ngl/gsknglglyphlibrary.c b/gsk/ngl/gsknglglyphlibrary.c index 33c86cc967..ede4f19105 100644 --- a/gsk/ngl/gsknglglyphlibrary.c +++ b/gsk/ngl/gsknglglyphlibrary.c @@ -21,7 +21,7 @@ #include "config.h" #include -#include +#include #include #include "gsknglcommandqueueprivate.h" @@ -237,7 +237,7 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary *self, pixel_data = free_data = g_malloc (width * height * 4); gdk_memory_convert (pixel_data, width * 4, - GDK_MEMORY_CONVERT_GLES_RGBA, + GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, cairo_image_surface_get_data (surface), width * 4, GDK_MEMORY_DEFAULT, diff --git a/gsk/ngl/gskngliconlibrary.c b/gsk/ngl/gskngliconlibrary.c index ab4d1b4d6f..cfc662a9e6 100644 --- a/gsk/ngl/gskngliconlibrary.c +++ b/gsk/ngl/gskngliconlibrary.c @@ -21,7 +21,7 @@ #include "config.h" #include -#include +#include #include #include @@ -115,7 +115,7 @@ gsk_ngl_icon_library_add (GskNglIconLibrary *self, { pixel_data = free_data = g_malloc (width * height * 4); gdk_memory_convert (pixel_data, width * 4, - GDK_MEMORY_CONVERT_GLES_RGBA, + GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, surface_data, cairo_image_surface_get_stride (surface), GDK_MEMORY_DEFAULT, width, height); gl_format = GL_RGBA; -- 2.30.2